#include "common.h"
#include "account_item.h"
#include <exception>
#include <fstream>
#include <stdexcept>
#include <string>


//-------------------- 1. 记账 --------------------
// 读取文件中的账目数据
void loadDataFromFile(std::vector<AccountItem>& items)
{
    std::ifstream input(FILENAME);

    // 逐行读取每一条账目， 包装成 AccountItem
    AccountItem item;
    while (input >> item.itemType >> item.amount >> item.detail)
    {
        items.push_back(item);
    }
}

// 记账
void accounting(std::vector<AccountItem>& items)
{
    // 读取键盘选择，并做合法性校验
    char key = readMenuSelection(3);

    switch (key)
    {
    case '1':   // 1 - 收入
        income(items);
        break;
    case '2':   // 2 - 支出
        expand(items);
        break;
    case '3':   // 3 - 返回主菜单
        break;
    default:
        break;
    }
    std::cout << std::endl;
}

// 记录一笔收入
void income(std::vector<AccountItem>& items)
{
    // 新构建一个 AccountItem 对象
    AccountItem item;

    // 类型已经确定， 就是收入
    item.itemType = INCOME;

    // 与用户交互， 键盘输入金额和备注信息
    std::cout << "\n本次收入金额: ";
    item.amount = readAmount();

    std::cout << "\n备注: ";
    getline(cin, item.detail);

    // 添加到 vector 中
    items.push_back(item);
    // 写入文件做持久化保存
    insertIntoFile(item);

    // 显示成功信息
    std::cout << "\n------------------- 记账成功! ----------------\n" << std::endl;
    std::cout << "\n请按回车键返回主菜单..." << std::endl;

    std::string line;
    getline(cin, line);
}

// 记录一笔支出
void expand(std::vector<AccountItem>& items)
{
    // 新构建一个 AccountItem 对象
    AccountItem item;

    // 类型已经确定， 就是收入
    item.itemType = EXPAND;

    // 与用户交互， 键盘输入金额和备注信息
    std::cout << "\n本次支出金额: ";
    item.amount = -readAmount();

    std::cout << "\n备注: ";
    getline(cin, item.detail);

    // 添加到 vector 中
    items.push_back(item);
    // 写入文件做持久化保存
    insertIntoFile(item);

    // 显示成功信息
    std::cout << "\n------------------- 记账成功! ----------------\n" << std::endl;
    std::cout << "\n请按回车键返回主菜单..." << std::endl;

    std::string line;
    getline(cin, line);
}

// 将一条账目写入文件中
void insertIntoFile(const AccountItem& item)
{
    std::ofstream output(FILENAME, std::ios::out | std::ios::app);

    output << item.itemType << "\t" << item.amount << "\t" << item.detail << std::endl;
    output.close();
}

// 读取键盘输入的金额数, 并做合法性校验
int readAmount()
{
    int amount;
    
    string str;
    while (true)
    {
        getline(cin, str);

        try
        {
            amount = std::stoi(str);
            break;
        }
        catch (std::invalid_argument e)
        {
            std::cout << "输入错误， 请正确输入数字: ";
        }
    }

    return amount;
}

//-------------------- 2. 查询 --------------------
void query(const std::vector<AccountItem>& items)
{
    // 读取键盘选择，并做合法性校验
    char key = readMenuSelection(4);

    switch (key)
    {
    case '1':   // 1 - 查询所有账目，并统计总收支
        queryItems(items);
        break;
    case '2':   // 2 - 查询收入， 统计总收入
        queryItems(items, INCOME);
        break;
    case '3':   // 3 - 查询支出， 统计总支出
        queryItems(items, EXPAND);
        break;
    case '4':
        break;
    default:
        break;
    }
    std::cout << std::endl;
}

// 查询账目功能函数
void queryItems(const std::vector<AccountItem>& items)
{
    std::cout << "---------- 查询结果 ----------" << std::endl;
    std::cout << "\n 类型\t\t金额\t\t备注\n" << std::endl;

    // 遍历所有账目， 统计总收支
    int total = 0;
    for (auto item : items)
    {
        printItem(item);
        total += item.amount;
    }

    // 输出信息
    std::cout << "========================================" << std::endl;
    std::cout << "总收支: " << total << std::endl;
    std::cout << "\n请按回车键返回主菜单..." << std::endl;

    std::string line;
    getline(cin, line);
}

// 打印输出一条账目信息
void printItem(const AccountItem& item)
{
    std::cout << item.itemType << "\t\t" << item.amount << "\t\t" << item.detail << std::endl;
}

// 函数重载
void queryItems(const std::vector<AccountItem>& items, const std::string itemType)
{
    std::cout << "---------- 查询结果 ----------" << std::endl;
    std::cout << "\n 类型\t\t金额\t\t备注\n" << std::endl;

    // 遍历所有账目， 统计总收支或总支出
    int total = 0;
    for (auto item : items)
    {
        if (item.itemType == itemType)
        {
            printItem(item);
            total += item.amount;
        }
    }

    // 输出信息
    std::cout << "========================================" << std::endl;
    std::cout << ((itemType == INCOME) ? "总收入: " : "总支出") << total << std::endl;
    std::cout << "\n请按回车键返回主菜单..." << std::endl;

    std::string line;
    getline(cin, line);
}